23 #define foreach(x, v) for (typeof (v).begin() x=(v).begin(); x !=(v).end(); ++x)
24 #define For(i, a, b) for (int i=(a); i<(b); ++i)
25 #define D(x) cout << #x " is " << x << endl
27 #define dassert(x) if (false) { assert(x); }
33 node(const string
&lbl
) : label(lbl
) { }
35 dassert(label
.size() > 0);
36 return sons
.size() == 0 and isupper(label
[0]);
39 dassert(label
.size() > 0);
40 return sons
.size() == 0 and islower(label
[0]);
43 dassert(label
.size() > 0);
44 if (sons
.size() == 0) dassert(islower(label
[0]));
45 return sons
.size() > 0;
50 node
parse(const string
&s
, int i
, int j
) {
51 if (s
[j
] != ')') { // constant or variable
52 return node(s
.substr(i
, j
- i
+ 1));
56 int k
= i
; while (s
[k
] != '(') k
++;
57 node ans
= node(s
.substr(i
, k
- i
));
58 // split string from [k+1, j-1]
60 for (i
= k
+ 1; i
< j
; ) {
63 if (s
[k
] == ')') balance
--;
64 if (s
[k
] == '(') balance
++;
65 if (k
== j
or s
[k
] == ',' and balance
== 0) {
66 node son
= parse(s
, i
, k
- 1);
67 ans
.sons
.push_back(son
);
78 void print(const node
&t
, int depth
= 0) {
79 for (int i
= 0; i
< depth
; ++i
) printf(" ");
80 printf("%s\n", t
.label
.c_str());
81 for (int i
= 0; i
< t
.sons
.size(); ++i
) {
82 print(t
.sons
[i
], depth
+ 1);
87 map
<string
, node
> mapping
;
89 bool contains(node r
, const string
&variable
, int depth
= 0) {
90 while (r
.isVariable() and mapping
.count(r
.label
) > 0) r
= mapping
[r
.label
];
91 if (r
.label
== variable
) return true;
92 for (int i
= 0; i
< r
.sons
.size(); ++i
) {
93 if (contains(r
.sons
[i
], variable
, depth
+ 1)) return true;
99 bool unify(const node
&A
, const node
&B
, int depth
= 0) {
100 //if (depth > 4) return false; // Remove this and you'll get a runtime error. Change for depth > 4 and you'll get a runtime error too.
102 while (a
.isVariable() and mapping
.count(a
.label
) > 0) {
103 a
= mapping
[a
.label
];
105 while (b
.isVariable() and mapping
.count(b
.label
) > 0) {
106 b
= mapping
[b
.label
];
109 if (a
.isConstant()) {
110 if (b
.isFunction()) return false;
111 if (b
.isConstant()) {
112 if (a
.label
== b
.label
) return true;
117 if (b
.isConstant()) {
118 if (a
.isFunction()) return false;
119 if (a
.isConstant()) {
120 if (a
.label
== b
.label
) return true;
125 if (a
.isVariable() and b
.isVariable()) {
126 if (a
.label
== b
.label
) return true;
128 mapping
[a
.label
] = b
;
133 if (a
.isVariable()) {
134 dassert(!b
.isVariable());
135 if (contains(b
, a
.label
)) return false;
137 mapping
[a
.label
] = b
;
143 dassert(!a
.isVariable());
144 if (contains(a
, b
.label
)) return false;
146 mapping
[b
.label
] = a
;
151 // both are functions
152 dassert(a
.isFunction() and b
.isFunction());
153 if (a
.label
!= b
.label
) return false;
154 if (a
.sons
.size() != b
.sons
.size()) return false;
155 for (int i
= 0; i
< a
.sons
.size(); ++i
) {
156 bool r
= unify(a
.sons
[i
], b
.sons
[i
], depth
+ 1);
157 if (!r
) return false;
163 string s
= "f(X,g(c))";
165 // s = "f(c,g(Y,d))";
167 // s = "f(f(f(X,a),a),a)";
168 // s = "f(f(f(f(f(f(f(f(f(f(f(X)),d)))),e,f,g(c,c))))),a,a,a,a,a)";
169 // s = "f(f(f(f(f(f(f(f(f(f(f(X)),d)))),e,f,g(c,c))))),a,a,a,a,a,f(f(f(f(f(a,n,d,y,m,e,j,i,a,f(f(f(f(f(f(X))))))))))))";
173 //node t = parse(s, 0, s.size() - 1);
176 while (cin
>> name
>> n
) {
177 if (name
== "END" and n
== 0) break;
178 vector
<node
> trees(n
);
179 for (int i
= 0; i
< n
; ++i
) {
180 string expression
; cin
>> expression
;
181 trees
[i
] = parse(expression
, 0, expression
.size() - 1);
185 for (int i
= 0; i
< n
- 1 and works
; ++i
) {
186 works
&= unify(trees
[i
], trees
[i
+1]);
189 printf("analysis inconclusive on %s\n", name
.c_str());
191 printf("%s is a Starflyer agent\n", name
.c_str());